﻿using System;
using System.Linq;
using System.ServiceModel;
using Framework.Core;
using Framework.Core.BootStrapper.WindowsService;
using Framework.Core.Io;
using Framework.Remoting.Hosting;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Wcf.Hosting
{
    public class WcfHostTest
    {
        private readonly WcfHost<WindowsServiceArgs> target;

        private readonly MockRepository mockRepository = new MockRepository();
        private readonly IServiceHostFactory<ServiceHost> serviceHostFactoryMock;
        private readonly IAssemblyAdapter assemblyAdapterMock;

        public WcfHostTest()
        {
            serviceHostFactoryMock = mockRepository.StrictMock<IServiceHostFactory<ServiceHost>>();
            assemblyAdapterMock = mockRepository.StrictMock<IAssemblyAdapter>();
            target = new WcfHost<WindowsServiceArgs>(serviceHostFactoryMock, assemblyAdapterMock);
        }

        [Fact]
        public void Test_GetServices_Succeed()
        {
            assemblyAdapterMock
                .Expect(x => x.GetEntryAssembly())
                .Return(GetType().Assembly);

            mockRepository.ReplayAll();
            var actual = target.GetServices();
            mockRepository.VerifyAll();
            Assert.NotNull(actual);
            // ReSharper disable PossibleMultipleEnumeration
            Assert.Equal(4, actual.Count());
            // ReSharper restore PossibleMultipleEnumeration
            // ReSharper disable PossibleMultipleEnumeration
            Assert.True(actual.Contains(typeof(Contract)));
            // ReSharper restore PossibleMultipleEnumeration
        }

        private void AssertState(CommunicationState communicationState)
        {
            target.Hosts.ForEach(h => Assert.True(h.State == communicationState));
        }

        private void MockDependencies()
        {
            assemblyAdapterMock
                .Expect(x => x.GetEntryAssembly())
                .Return(GetType().Assembly);

            serviceHostFactoryMock
                .Expect(x => x.Create(
                    Arg<Type>.Is.NotNull,
                    Arg<EnvMode>.Is.Equal(EnvMode.Dev)))
                .Return(new ServiceHost(typeof(Contract),
                                           new Uri(
                                               "net.tcp://localhost:10301/Framework.Wcf.Hosting.HasFailed/IDummyContract/")))
                .Repeat.Any();
        }

        [Fact]
        public void Test_that_4_host_have_been_started()
        {
            MockDependencies();
            mockRepository.ReplayAll();
            target.Start(new WindowsServiceArgs());
            Assert.Equal(4, target.Hosts.Count);
            //Created because service can't be Opened in UT
            AssertState(CommunicationState.Created);
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Test_that_host_has_been_closed_when_service_was_closed()
        {
            MockDependencies();

            serviceHostFactoryMock.Expect(x => x.Close(null)).IgnoreArguments().Repeat.Any();
            mockRepository.ReplayAll();
            target.Start(new WindowsServiceArgs());
            target.Stop();
            mockRepository.VerifyAll();
        }

        [Fact]
        public void Test_that_wcfhost_can_be_construct_whithout_args()
        {
            Assert.NotNull(new WcfHost<WindowsServiceArgs>());
        }
    }
}